import type { MaskitoOptions, MaskitoPreprocessor } from '@maskito/core'
import {
	maskitoAddOnFocusPlugin,
	maskitoCaretGuard,
	maskitoPrefixPostprocessorGenerator,
	maskitoRemoveOnBlurPlugin
} from '@maskito/kit'
import { useMaskito } from '@maskito/react'
import { InputAdornment, TextField, type TextFieldProps } from '@mui/material'
import { type Control, Controller } from 'react-hook-form'

import { CopyButton } from '@/components/CopyButton'

const phoneMaskOptions = {
	mask: [
		'+',
		'7',
		' ',
		/\d/,
		/\d/,
		/\d/,
		' ',
		/\d/,
		/\d/,
		/\d/,
		'-',
		/\d/,
		/\d/,
		'-',
		/\d/,
		/\d/
	],
	postprocessors: [
		// non-removable country prefix
		maskitoPrefixPostprocessorGenerator('+7 ')
	],
	preprocessors: [createCompletePhoneInsertionPreprocessor()],
	plugins: [
		maskitoAddOnFocusPlugin('+7 '),
		maskitoRemoveOnBlurPlugin('+7 '),
		// Forbids to put caret before non-removable country prefix
		// But allows to select all value!
		maskitoCaretGuard((value, [from, to]) => [
			from === to ? '+7 '.length : 0,
			value.length
		])
	]
} as MaskitoOptions

// Paste "89123456789" => "+7 (912) 345-67-89"
function createCompletePhoneInsertionPreprocessor(): MaskitoPreprocessor {
	const trimPrefix = (value: string): string =>
		value.replace(/^(\+?7?\s?8?)\s?/, '')
	const countDigits = (value: string): number =>
		value.replaceAll(/\D/g, '').length

	return ({ elementState, data }) => {
		const { value, selection } = elementState

		return {
			elementState: {
				selection,
				value: countDigits(value) > 11 ? trimPrefix(value) : value
			},
			data: countDigits(data) >= 11 ? trimPrefix(data) : data
		}
	}
}

export const TextFieldControlled = (
	props: TextFieldProps & {
		control: Control<any>
		name: string
		label: string
		readOnly?: boolean
		copyBtn?: boolean
	}
) => {
	const {
		control,
		name,
		label,
		copyBtn = false,
		readOnly = false,
		...rest
	} = props

	const maskedInputRef = useMaskito({ options: phoneMaskOptions })

	return (
		<Controller
			name={name}
			control={control}
			render={({ field, fieldState }) => (
				<TextField
					{...field}
					{...rest}
					label={label}
					error={!!fieldState.error}
					helperText={fieldState.error?.message}
					variant='outlined'
					InputProps={{
						readOnly: readOnly,
						endAdornment: copyBtn && field.value && (
							<InputAdornment position='end'>
								<CopyButton
									text={field.value}
									size={20}
								/>
							</InputAdornment>
						),
						fullWidth: true
					}}
					fullWidth
					ref={rest.type === 'tel' ? maskedInputRef : undefined}
					onInput={
						rest.type === 'tel'
							? e => field.onChange((e.target as HTMLInputElement).value)
							: undefined
					}
				/>
			)}
		/>
	)
}
